#! /usr/bin/env python
# -*- coding: utf-8 -*-

import re
import os
import time

import FileHostProtoType


class hfitem(FileHostProtoType.HostItem):
    def __init__(self, name, type, id, link, encrypt_name='', server_name=''):     
        #'type' would save fullpath, if it is a folder
        FileHostProtoType.HostItem.__init__(self, name, type, id, link, encrypt_name, server_name)

class hotfile(FileHostProtoType.FileHostProcess):
    def __init__(self,user,pwd):
        FileHostProtoType.FileHostProcess.__init__(self)
        self.hostname = "HotFile"
        self._opener = None
        self._user = user
        self._pwd = pwd
        self.logtype = 'poster'
        self.islogin = False
            
    def login(self):
        '''
        login to hotfile
        return opener object which includes cookies
        '''
        if self.islogin == True:
            return True
        self.fherr.write('login to hotfile %s/%s...' % (self._user,'*'*len(self._pwd)))
        loginData = {'returnto' : '/', \
                'user' : self._user, \
                'pass' : self._pwd}
        loginresult =  self.loginFileHost("http://hotfile.com/login.php", loginData)
        #you always see you username at the top of the page, if it logins successfully.
        if self._user not in loginresult:
            self.fherr.write("User %s Faile to Login Hotfile." % self._user)
            return False
        self.fherr.write("User %s logined." % self._user)
        self.islogin = True
        return True
        
    def getFileList(self, days=0):
        '''
        '''
        self.fherr.write("Listing files...")
        hfitems = []
        url = "http://hotfile.com/myfiles.html"
        response = self.post_request(url)
        #get all filelist page by data
        FilesListLinkOtherDays = []
        reMyfileDateLink = re.compile("myfiles.html\?d=\d+-\d+-\d+")
        dates = reMyfileDateLink.findall(response)
        if dates is not None:
            FilesListLinkOtherDays = ["http://hotfile.com/"+d for d in dates]
        reFileDlLink = re.compile('(?P<DlLink>http://hotfile.com/dl/(?P<id>\d+)/.*?.html)\';(.*?)<label><a href="/links/.*?">(?P<Name>.*?)</a></label>',\
                                      re.I|re.S)    
        if days == 0:
            days = len(FilesListLinkOtherDays)
        FilesListLinkOtherDays.reverse()
        FilesListLinkOtherDays = FilesListLinkOtherDays[0:days]     

        while len(FilesListLinkOtherDays)> 0 : 
            link = FilesListLinkOtherDays.pop()
            self.fherr.write("fetching...%s" % link)
            response += self.post_request(link)
        dlLinksRaw = reFileDlLink.finditer(response)
        for l in dlLinksRaw:
            item = hfitem(l.group('Name'), 'file', l.group('id'), l.group('DlLink'))
            hfitems.append(item)
        hfitems.sort()
        return hfitems
    
    def getSimpleFolderList(self):
        '''
        get a simple folderlist with only name&id, without folder link
        but this function would very fast, if there are a lot of subdirs.
        '''
        self.fherr.write("Getting folders...")
        
        folders = []
        # get a compelete folder list, but only with name and id
        url = "http://hotfile.com/myfolders.html"
        response = self.post_request(url)              
        reSelectFolder = re.compile('<option value="(?P<id>\d{2,})">(?P<name>.*?)</option>', re.I|re.S)
        allFolder = reSelectFolder.finditer(response)
        for a in allFolder:
            fullpath = a.group('name')
            name = os.path.split(os.path.normpath(fullpath))[1]
            id = a.group('id')
            item = hfitem(name, fullpath, id, '')
            folders.append(item)
        # folders contains duplicate items, but it doesn't matter
        return folders
    
    def get_folder_link_by_id(self, folderitem):
        folderid = folderitem.id
        url = "http://hotfile.com/myfolders.html?o=" + folderid
        response = self.post_request(url)
        reFolderInfo = re.compile("folderlinks\[" + folderid + "] = '(?P<link>https://hotfile\.com/list/\d+/\w+)';.*?filenames\[\d+\] = '(?P<name>\w+) ';", re.I|re.S)
        search_result = reFolderInfo.search(response)
        if search_result:
            item = hfitem(folderitem.name, 'folder', folderid, search_result.group('link'))
            return item
    
    def getFolderList(self):   
        self.fherr.write("Getting folders...") 
        foldid = ""    
        folders = {}
        folderIDs = []
        gotFolder = []
        currentID = ""
        while(1):
            url = "http://hotfile.com/myfolders.html" + foldid
            response = self.post_request(url)
            if len(folderIDs) == 0 and foldid == "":                
                reSelectFolder = re.compile('<option value="(?P<id>\d{2,})">(?P<name>.*?)</option>', re.I|re.S)
                allFolder = reSelectFolder.finditer(response)
                
                for a in allFolder:
                    folders[a.group('id')] = a.group('name')
                    if a.group('id') not in folderIDs:
                        folderIDs.append(a.group('id'))
                
            reFolderInfo = re.compile("folderlinks\[(?P<id>\d+)\] = '(?P<link>http://hotfile\.com/list/\d+/\w+)';.*?filenames\[\d+\] = '(?P<name>\w+) ';", re.I|re.S)
            fds = reFolderInfo.finditer(response)
            
            for e in fds:
                item = hfitem(e.group('name').strip(), 'folder', e.group('id'), e.group('link'))
                item.type = folders[item.id]
                if item.id in folderIDs:
                    folderIDs.remove(item.id) 
                    gotFolder.append(item)
                if item.id == currentID:
                    gotFolder.append(item)
            if len(folderIDs) == 0:
                break
            currentID = folderIDs.pop()
            foldid = "?o=%s" %(currentID)
        gotFolder.sort()
        return gotFolder
    
    def createFolder(self, newfolder):
        if re.compile("^[a-zA-z0-9-_]+$").match(newfolder.replace('/','')) == None:
            self.fherr.write("The Folder must be more than 2 symbols long and must consist only of A-Z,0-9,- and _")
            return None
        if newfolder[0] != '/':
            newfolder = '/'+newfolder
        if newfolder[-1] != '/':
            newfolder +='/'
        dirs = newfolder.split('/')[1:-1]
        cf = '/'
        foldertree = []
        for f in dirs:
            if f == "":
                continue
            if len(f) < 2:
                self.fherr.write("The Folder must be more than 2 symbols long and must consist only of A-Z,0-9,- and _")
                return None
            cf += f +'/'
            foldertree.append(cf)
            
        remoteFolders = self.getSimpleFolderList()
#        return None
        remoteFolderNames = [f.type for f in remoteFolders]
        index = 0
        for i in range(len(foldertree)):
            index = i
            if foldertree[i] in remoteFolderNames:                
                self.fherr.write('Folder %s exists.' % foldertree[i])
                if index == len(foldertree) - 1:
                    folder_item = remoteFolders[remoteFolderNames.index(foldertree[index])]
                    folder_item = self.get_folder_link_by_id(folder_item)
                    return folder_item
                continue
            else:                
                if i == 0:
                    parentFolder = None
                else:
                    parentFolder = remoteFolders[remoteFolderNames.index(foldertree[i-1])]
                break
        justCreated = None
        for i in range(index,len(foldertree)):
            self.fherr.write("Creating...%s" % foldertree[i])
            justCreated = self.__newFolder(dirs[i], parentFolder)
            if justCreated is None:
                self.fherr.write('Fail to create folder %s' % foldertree[i])
                return None
            parentFolder = justCreated
        justCreated.type = foldertree[-1]
        return justCreated

    def __newFolder(self, newfolder, parentfolder=None):
        data =[]
        pid = 0
        if parentfolder is not None:
            pid = parentfolder.id
        data.append(('parent', '0'))
        data.append(('o', pid))
        data.append(('newfolder', newfolder))
        data.append(('parent', pid))
        url = "http://hotfile.com/myfolders.html?o=%s"%pid
        response = self.post_request(url, data)        
        reErrStr = re.compile('<div style=".*?" id="errstr">(?P<message>.*?)</div>')
        errstr = reErrStr.finditer(response)
        for e in errstr:
            self.fherr.write('Message from Hotfile Host:')
            self.fherr.write(e.group('message'))
        
        time.sleep(5)
        response = self.post_request(url)  
        reFolderInfo = re.compile("folderlinks\[(?P<id>\d+)\] = '(?P<link>https://hotfile\.com/list/\d+/\w+)';.*?filenames\[\d+\] = '(?P<name>\w+) ';", re.I|re.S)
        fds = reFolderInfo.finditer(response)
        maxid = 0
        newCreated = None
        for e in fds:
            item = hfitem(e.group('name'), 'folder', e.group('id'), e.group('link'))
            if int(item.id) > maxid and item.name.strip() == newfolder:
                newCreated = item
        return newCreated
    
    def moveto(self, items, destFolder):
        if len(items) == 0:
            return
        data ={}
        data['dest'] = destFolder.id
        moveids = ""
        for i in items:
            moveids += i.id + ","
        data['moveid'] = moveids
        url = "http://hotfile.com/myfolders.html"
        self.fherr.write("Moving files to folder %s " % destFolder.type)
        response = self.post_request(url, data)        
        reErrStr = re.compile('<div style=".*?" id="errstr">(?P<message>.*?)</div>')
        errstr = reErrStr.finditer(response)
        for e in errstr:
            self.fherr.write('Message from HotFile Host:')
            self.fherr.write(e.group('message'))     
    
    def upload_web_local(self, file, progressLog=None, other_args=None, send_range=None):
        #access index page
        uploadpage = self.post_request("http://hotfile.com/")
        #vip user get a upload link with 'zz'
        reUploadLink = re.compile("http://u\d+.hotfile.com/upload.cgi\?z*\d+")
        uploadLink = reUploadLink.findall(uploadpage)
        if len(uploadLink) == 0:
            self.fherr.write("Can't get upload link, Wait for 1min and Retry...")
            return
        
        callback = None
        if progressLog is not None:
            callback = progressLog.write
        filesize = os.path.getsize(file)
        filename = self.rename_func(file)
        start_point = 0
        info = "Uploading...%s" % file
        if send_range is not None:
            #range is a 3-tuple, <start, end, number>
            filesize = send_range[1] - send_range[0] + 1
            filename += ".%03d" % send_range[2]
            start_point = send_range[0]
            info += " part%d" % send_range[2]
            
        self.fherr.write(info) 
        basename = os.path.basename(file)   
        fileobj = open(file, 'rb')
        fileobj.seek(start_point)  
        
        data = {'uploads[1]':fileobj}
        
        returnpage = self.post_request(uploadLink[0], data, cb=callback, retry=1, \
                                            setfilename=filename,\
                                            setfilesize=filesize)
        
        if returnpage is None:
            self.fherr.write("UploadTask(%s) was Failed" % file)
            return
        
        reFileLinkInside = re.compile("(?P<DlLink>https://hotfile.com/dl/(?P<id>\d+)/.*?.html)")
        m = reFileLinkInside.search(returnpage)        
        if m is not None:
            it = hfitem(basename, "file", m.group("id"), m.group("DlLink"), filename)
            self.newupload.append(it)
            self.fhout.write(it.format())                
            return it   
        
        self.fherr.write(returnpage)
        self.fherr.write("Fail to get link, Add to queue, wait for retry...")
        return  
    
    def upload_to_ftp(self, file, progressLog=None, other_args=None):
        url = 'ftp://ftp.hotfile.com' 
        userpwd = ('%s:%s' % (self._user, self._pwd)).encode('utf8')
        target_name = self.rename_func(file)
        callback = None
        if progressLog is not None:
            callback = progressLog.write
            
        self.fherr.write("Uploading...%s" % file)
        self.upload_file_to_ftp(url, userpwd, file, \
                                target=target_name.encode('utf8'), \
                                callback=callback)
        
        #find new upload file:
        time.sleep(10)    
        times = self.wait_time/60 + 1
        while times > 0:           
            last_two_days = self.getFileList(1)
            find_result = self.find([target_name.decode('utf8'),], last_two_days)
            if find_result:
                new_file = find_result[0]     
                item = hfitem(os.path.basename(file), \
                              'file', \
                              new_file.id, \
                              new_file.link, \
                              target_name.decode('utf8'),\
                              new_file.server_name)
                self.newupload.append(item)
                return item
            times -= 1
            time.sleep(60)
    
    def upload_web(self, file, progressLog=None, other_args=None, send_range=None):
        return self.upload_web_local(file, progressLog, other_args, send_range)

if __name__ == "__main__":
    pass